import path from 'path'
import jwt from 'jsonwebtoken'
import _ from 'lodash'
import { secret, expiresIn } from '../config.js'
import { User, userSchema } from '../models/users.js'
import { UserInfo, userInfoSchema } from '../models/user-info.js'
import { Follow } from '../models/follow.js'
import { errorResponse } from '../lib/format-error.js'

// 创建令牌
// keep 是否记住
// TODO 自动延长过期时间
function createToken(payload) {
    const {name, password, id, keep} = payload
    return jwt.sign({ name, password, id }, secret, { expiresIn: expiresIn })
}

function returnUserInfo(data) {
    return {
        id: data.id || '',
        name: data.name || '',
        nickname: data.nickname || '',
        avatarUrl: data.avatarUrl || '',
        gender: data.gender || 0,
        area: data.area || [],
        birthday: data.birthday || '',
        brief: data.brief || '',
        follow: 0,
        fans: 0
    }
}

class UsersCtl {
    // 查询用户是否存在
    async checkUser(ctx) {
        const exist = await User.userExist({name: ctx.query.name})
        if(exist) {
            ctx.throw(406)
            return
        } else {
            ctx.body = {
                code: 200,
                data: exist
            }
        }
    }
    // 登录
    async login(ctx) {
        ctx.verifyParams(userSchema)
        const { name, password } = ctx.request.body
        const exist = await User.userExist({name, password})
        if(!exist) {
            ctx.throw(405)
        } else {
            const user = await User.findOne({ name: name })
            const token = createToken(_.assign(ctx.request.body, { id: user.id }))
            ctx.body = {
                code: 200,
                token: token
            }
        }
    }
    // 查找
    async find(ctx) {
        ctx.body = await User.find()
    }
    // 创建
    async create(ctx) {
        ctx.verifyParams(userSchema)
        const { name } = ctx.request.body
        const exist = await User.userExist({name: name})
        if(exist) {
            ctx.throw(406)
            return
        }
        const user = await User.save(ctx.request.body)
        ctx.body = {
            code: 200,
            data: user.data
        }
    }
    // 更新
    async update(ctx) {
    }
    // 上传头像
    async uploadAvatar(ctx) {
        const authUser = ctx.state.user
        const file = ctx.request.files.file
        const basename = path.basename(file.filepath)
        const url = `${ctx.origin}/uploads/${basename}`
        await UserInfo.updateAvatar(authUser.id, url)
        ctx.body = {
            code: 200,
            url: url
        }
    }
    // 更新用户信息
    async updateInfo(ctx) {
        ctx.verifyParams(userInfoSchema)
        const body = ctx.request.body
        const data = await UserInfo.findById(body.id)
        const { nickname, gender, area, birthday, brief } = body
        const saveParams = {nickname, gender, area, birthday, brief}
        const res = _.isEmpty(data)
            ? await UserInfo.create(body.id, saveParams)
            : await UserInfo.update(body.id, saveParams)
        
        ctx.body = {
            code: 200,
            data: res
        }
    }
    // 检查是否为自己
    async checkOwner(ctx, next) {
        // const id = ctx.request.body.id || ctx.params.id
        // if(ctx.params.id !== ctx.state.user.id) {
        if(ctx.request.body.id !== ctx.state.user.id) {
            ctx.throw(403)
        }
        await next()
    }
    // 获取当前登录用户信息
    async getMyInfo(ctx) {
        const authUser = ctx.state.user
        if(_.isEmpty(authUser)) ctx.throw(404)
        const res = await UserInfo.findById(authUser.id)
        res.name = authUser.name
        res.id = authUser.id
        res.nickname = res.nickname || authUser.name
        ctx.body = {
            code: 200,
            data: returnUserInfo(res)
        }
    }
    // 查询用户信息
    async getUserInfo(ctx) {
        const id = ctx.query.id
        if(!id) ctx.throw(400)
        const user = await User.findOne({ id: id })
        if(!user) ctx.throw(400)
        // TODO 判断是否为自己查自己
        const res = await UserInfo.findById(ctx.query.id)
        res.name = user.name
        res.id = user.id
        ctx.body = {
            code: 200,
            data: returnUserInfo(res)
        }
    }
    // 关注某人
    async following(ctx) {
        const me = ctx.state.user.id
        const { id } = ctx.request.body
        const user = await User.findOne({ id: id })
        if(!user) {
            ctx.body = errorResponse(1001)
        } else {
            // 查询是否已经关注
            const flag = await Follow.checkFollowing(me)
            if(!flag) {
                await Follow.following(me, id)
                ctx.body = {
                    code: 200
                }
            } else {
                ctx.body = errorResponse(1002)
            }
        }
    }
    // 取消关注
    async unFollowing(ctx) {
        const me = ctx.state.user.id
        const { id } = ctx.request.body
        const user = await User.findOne({ id: id })
        if(!user) {
            ctx.body = errorResponse(1001)
        } else {
            const flag = await Follow.checkFollow(id, me)
            if(!flag) {
                ctx.body = errorResponse(1003)
            } else {
                await Follow.unFollowing(me, id)
                ctx.body = {
                    code: 200
                }
            }
        }
    }
    // 获取粉丝信息列表
    async getFollowers(ctx) {
        const { id, offset = 20 } = ctx.query
        if(!id) {
            errorResponse(1001)
        } else {
            // 判断是否为自己, 非自己需要判断对方是否屏蔽了粉丝权限
            // const me = ctx.state.user
            const res = await Follow.followList(id, offset, 0)
            ctx.body = {
                code: 200,
                list: res
            }
        }
    }
    // 获取关注列表
    async getFollowings(ctx) {
        const { id, offset = 20 } = ctx.query
        if(!id) {
            errorResponse(1001)
        } else {
            const me = ctx.state.user
            if(!me) {

            } else {
                const res = await Follow.followList(id, offset, 1)
                ctx.body = {
                    code: 200,
                    list: res
                }
            }
        }
    }
}

export default new UsersCtl()